﻿using ComputedTable.Version10;
using Microsoft.VisualBasic;
using System;

namespace MortgageCalculator.Demo
{
    public interface IInterestCalculator : ICalculator<MortgageCalculatorOperationContext>
    {
    }

    public class InterestCalculator : IInterestCalculator
    {
        public CellOperationResult Execute(MortgageCalculatorOperationContext context)
        {
            var result = (decimal)Financial.IPmt(
                           (double)(context.Input.InterestRate / 12),
                           context.CurrentCell.RowId,
                           context.Input.DurationOfLoan,
                           -(double)context.Input.LoanAmount);
            context.TotalInterestPaid += result;
            context.TotalLoanPayments += result;
            return CellOperationResult.CreateSucceed(Decimal.Round(result, 2));
        }
    }

    public interface IPrincipalCalculator : ICalculator<MortgageCalculatorOperationContext>
    {
    }

    public class PrincipalCalculator : IPrincipalCalculator
    {
        public CellOperationResult Execute(MortgageCalculatorOperationContext context)
        {
            var result = (decimal)Financial.PPmt(
                   (double)(context.Input.InterestRate / 12),
                   context.CurrentCell.RowId,
                   context.Input.DurationOfLoan,
                   -(double)context.Input.LoanAmount);
            context.TotalLoanPayments += result;
            return CellOperationResult.CreateSucceed(Decimal.Round(result, 2));
        }
    }

    
    public interface ITotalPaymentsCalculator : ICalculator<MortgageCalculatorOperationContext>
    {
    }

    public class TotalPaymentsCalculator : ITotalPaymentsCalculator
    {
        public CellOperationResult Execute(MortgageCalculatorOperationContext context)
        {
            var interest = context.Table[context.CurrentCell.RowId, AmortizationTableColumns.Interest].GetValueAsDecimal();
            var principal = context.Table[context.CurrentCell.RowId, AmortizationTableColumns.Principal].GetValueAsDecimal();
            var propertyTax = context.Table[context.CurrentCell.RowId, AmortizationTableColumns.PropertyTax].GetValueAsDecimal();

            decimal result = interest + principal + propertyTax;
            return CellOperationResult.CreateSucceed(Decimal.Round(result, 2));
        }
    }

    public interface IClosingBalanceCalculator : ICalculator<MortgageCalculatorOperationContext>
    {
    }

    public class ClosingBalanceCalculator : IClosingBalanceCalculator
    {
        public CellOperationResult Execute(MortgageCalculatorOperationContext context)
        {
            var principal = context.Table[context.CurrentCell.RowId, AmortizationTableColumns.Principal].GetValueAsDecimal();
            var openingBalance = context.Table[context.CurrentCell.RowId, AmortizationTableColumns.OpeningBalance].GetValueAsDecimal();

            decimal result = openingBalance - principal;
            return CellOperationResult.CreateSucceed(Decimal.Round(result, 2));
        }
    }

    public interface IOpeningBalanceCalculator : ICalculator<MortgageCalculatorOperationContext>
    {
    }

    public class OpeningBalanceCalculator : IOpeningBalanceCalculator
    {
        public CellOperationResult Execute(MortgageCalculatorOperationContext context)
        {
            var previousCell = context.Table.Up(context.CurrentCell);
            if (previousCell == null)
            {
                return CellOperationResult.CreateSucceed(context.Input.LoanAmount);
            }

            var result = context.Table[previousCell.RowId, AmortizationTableColumns.ClosingBalance].GetValueAsDecimal();
            return CellOperationResult.CreateSucceed(result);
        }
    }
}
